package org.infodavid.common.impl.services;

import java.util.List;

import javax.persistence.PersistenceException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.infodavid.common.annotations.AImplementation;
import org.infodavid.common.annotations.AImplementation.ERuntime;
import org.infodavid.common.dto.IPersonListItem;
import org.infodavid.common.impl.services.helpers.ServiceHelper;
import org.infodavid.common.model.IPerson;
import org.infodavid.common.model.criteria.IPersonCriteria;
import org.infodavid.common.persistence.IQueryParameter;
import org.infodavid.common.persistence.PersonDataService;
import org.infodavid.common.services.IApplicationContext;
import org.infodavid.common.services.PersonService;
import org.infodavid.common.services.exceptions.ServiceException;

/**
 * The Class PersonServiceImpl.
 */
@AImplementation(value = PersonService.class, runtime = ERuntime.DEFAULT)
public class PersonServiceImpl extends PersonService {

  /** The Constant log. */
  private static final Log LOGGER = LogFactory.getLog(PersonServiceImpl.class);

  /** The helper. */
  private final ServiceHelper<IPersonListItem,IPerson,Long,IPersonCriteria> helper;

  /**
   * The Constructor.
   */
  protected PersonServiceImpl() {
    super();

    helper =
        new ServiceHelper<IPersonListItem,IPerson,Long,IPersonCriteria>(
            PersonDataService.getInstance());
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.services.AbstractEntityService#add(org.infodavid.common.services.
   * IApplicationContext, org.infodavid.common.model.IDataObject)
   */
  public long add(final IApplicationContext context, final IPerson value)
      throws PersistenceException, ServiceException {
    helper.validate(context, getValidator(), value);

    final IInterceptorEvent evt = preExecute(context, ADD_ACTION, value);
    final long key = helper.add(context, value).longValue();

    postExecute(evt);

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("A new person has been added: " + value + " (" + key + ')');
    }

    return key;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.services.PersonService#findByName(org.infodavid.common.services.
   * IApplicationContext, java.lang.String, java.util.List, java.util.List)
   */
  @Override
  public long findByName(final IApplicationContext context, final String value,
      final List<IPersonListItem> entities, final List<IQueryParameter> parameters)
      throws PersistenceException, ServiceException {
    if (StringUtils.isEmpty(value)) {
      throw new IllegalArgumentException(IPerson.NAME);
    }

    ServiceUtil.validate(context);
    helper.validate(entities);

    final IInterceptorEvent evt = preExecute(context, FIND_ACTION, value);
    final long result =
        ((PersonDataService)helper.getDataService()).findByName(context.getPersistenceSession(),
            value, entities, parameters);

    postExecute(evt.setResults(entities));

    return result;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.services.AbstractEntityService#get(org.infodavid.common.services.
   * IApplicationContext, long)
   */
  @SuppressWarnings("boxing")
  public IPerson get(final IApplicationContext context, final long key)
      throws PersistenceException, ServiceException {
    helper.validate(context, key);

    final IInterceptorEvent evt = preExecute(context, GET_ACTION, key);
    final IPerson result = helper.get(context, key);

    postExecute(evt.setResults(result));

    return result;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.services.AbstractEntityService#getEntities(org.infodavid.common.services.
   * IApplicationContext, java.util.List, org.infodavid.common.services.ISearchCriteria)
   */
  public long findEntities(final IApplicationContext context, final List<IPersonListItem> entities,
      final IPersonCriteria criteria) throws PersistenceException, ServiceException {
    ServiceUtil.validate(context);
    helper.validate(entities);

    final IInterceptorEvent evt = preExecute(context, FIND_ACTION, criteria);
    final long result =
        ((PersonDataService)helper.getDataService()).find(context.getPersistenceSession(),
            entities, criteria);

    postExecute(evt.setResults(entities));

    return result;
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.services.AbstractEntityService#remove(org.infodavid.common.services.
   * IApplicationContext, long)
   */
  @SuppressWarnings("boxing")
  public void remove(final IApplicationContext context, final long key)
      throws PersistenceException, ServiceException {
    helper.validate(context, key);

    final IInterceptorEvent evt = preExecute(context, REMOVE_ACTION, key);

    helper.remove(context, key);
    postExecute(evt.setResults(key));

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("A person has been removed: " + key);
    }
  }

  /*
   * See super class or interface. (non-Javadoc)
   * @see org.infodavid.common.services.AbstractEntityService#update(org.infodavid.common.services.
   * IApplicationContext, org.infodavid.common.model.IDataObject)
   */
  public void update(final IApplicationContext context, final IPerson value)
      throws PersistenceException, ServiceException {
    helper.validate(context, getValidator(), value);

    final IInterceptorEvent evt = preExecute(context, UPDATE_ACTION, value);

    helper.update(context, value);
    postExecute(evt.setResults(value));

    if (LOGGER.isDebugEnabled()) {
      LOGGER.debug("A person has been updated: " + value + " (" + value.getKey() + ')');
    }
  }
}
